package com.clq;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.clq.annotate.Autowired2;
import com.clq.annotate.Controller2;
import com.clq.annotate.ResponseBody2;
import com.clq.annotate.Service2;
import com.clq.utils.ResponseUtils;

public class App extends HttpServlet{
	/**
	 * @author chenluqiang
	 * @date 2019年3月29日 下午5:25:17 
	 *
	 */
	private static final long serialVersionUID = 2215029937096202658L;
	private static Map<String,Object> serviceImplCMap = new HashMap<String,Object>();
	private static Map<String,Object> controllerObjMap = new HashMap<String,Object>();
	
	public static void main(String[] args) throws Throwable {
		//@Autowird 注解实现
//		App.run(""); 
		//spring AOP的实现
		/*TestService t = (TestService) new DynaProxyHello().bind(new Cat(),new TestServiceImpl());
		t.test();*/
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		 //设置字符编码
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		String path = req.getServletPath().toString();
		if(path!=null&&path!=""&&path.length()>0) {
			if(path.contains(".html")) {
				this.gotoPage(req,resp,path);
			}else {
				resp.getWriter().append("Hello world").println();
				try {
					run(path,req,resp);
				} catch (Throwable e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void gotoPage(HttpServletRequest request, HttpServletResponse response,String path) throws IOException {
		
		// 动态获取服务器路径
		// 获取应运程序上下文环境
		ServletContext sc = request.getServletContext();
		String path2 = sc.getRealPath("/");
		String filePath = path2 +"/WEB-INF"+ path;
		FileInputStream fis = new FileInputStream(filePath);
		BufferedReader br = new BufferedReader(new InputStreamReader(fis));
		String line = null;
		while ((line = br.readLine()) != null) {
			PrintWriter out = response.getWriter();
			out.print(line);
		}
	}

	public  void run(String path,HttpServletRequest req,HttpServletResponse res) throws Throwable {
		//找class
		initClass();
		String[] keys = null;
		if(path.indexOf("/")!=-1) {
			keys = path.split("/");
		}
		if(keys!=null&&keys.length!=0&&controllerObjMap.keySet().contains(keys[1])&&keys[1]!=null) {
			Object obj = controllerObjMap.get(keys[1]);
			init(obj);
			InvocationHandler handler = new InvocationHandler() {
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					method.setAccessible(true);
					return method.invoke(proxy, args);
				}
			};
			try {
				boolean flag = true;
				Method method = obj.getClass().getDeclaredMethod(keys[2]);
				//json格式返回
				for(Annotation ano : method.getAnnotations()) {
					if(ano.annotationType().isAssignableFrom(ResponseBody2.class)) {
						flag = false;
					}
				}
				Object invoke = handler.invoke(obj, method,null);
				ResponseUtils.returnJsonOrPage(req, res, invoke, flag);
			}catch (NoSuchMethodException | ArrayIndexOutOfBoundsException e) {
//				System.out.println("404 Not Fount!");
				res.getWriter().append("404 Not Fount!!"+e.getMessage()).println();
				e.printStackTrace();
			}
//				break;
		}else {
//			System.out.println("404 Not Fount!");
			res.getWriter().append("404 Not Fount!!!").println();
		}
	}
	public void initClass() throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
		List<Map<String,Object>> classFiles = new ArrayList<>();
		String basePath =this.getClass().getResource("/").getFile();
		File baseFiles = new File(basePath);
		//搜索所有class
		seachFiles(classFiles,baseFiles,baseFiles.getPath());
		//找存在注解的class 
		seachAnno(classFiles);
	}
	
	@SuppressWarnings("rawtypes")
	private static void seachAnno(List<Map<String,Object>> list) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
		for(Map<String,Object> map : list) {
			if(map!=null&&map.get("ppath")!=null&&map.get("ppath").toString()!=null&&map.get("ppath").toString().length()!=0) {
				Class clazz = Class.forName(map.get("ppath").toString());
				//获取类上的注解
				for(Annotation anno : clazz.getDeclaredAnnotations()) {
					//判断是否存在Service2注解
					if(anno.annotationType().isAssignableFrom(Service2.class)) {
						for(Class service: clazz.getInterfaces()) {
							serviceImplCMap.put(service.getName(),clazz);
						}
					}else if(anno.annotationType().isAssignableFrom(Controller2.class)) {
						String val = ((Controller2)anno).value();
						if(val!=null&&val.length()!=0) {
//							controllerObjMap.put(val, clazz);
							controllerObjMap.put(val, clazz.newInstance());
						}
					}
				}
			}
		}
	}

	private static void seachFiles(List<Map<String,Object>> list,File baseFiles,String basePath){
		for(File f : baseFiles.listFiles()) {
			if(f.exists()) {
				//如果是文件夹，继续
				if(f.isDirectory()) {
					seachFiles(list,f,basePath);
				}
				else if(f.getName().contains(".class")) {
					Map<String,Object> tempMap = new HashMap<String,Object>();
					String ppath = f.getPath().replace(basePath, "");
					ppath = ppath.substring(1, ppath.length());
					ppath = ppath.replace("\\",".");
					ppath = ppath.replace(".class", "");
					tempMap.put("ppath",ppath);
					tempMap.put("file",f);
					list.add(tempMap);
				}
			}
		}
	}
	
	@SuppressWarnings("rawtypes")
	private static void init(Object ... objs) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
		for(Object obj : objs) {
			Class clazz =  obj.getClass();
			//遍历clazz下的所有属性。
			for(Field field : clazz.getDeclaredFields()) {
				 if (field.isAnnotationPresent(Autowired2.class)) {  //判断属性是否是自定义注解@MyAnnotation
		                if(!field.getType().isInterface()) {  //加自定义注解的属性必须是接口类型（这样才可能出现多个不同的实例bean)
		                    throw new ClassNotFoundException("Annotation field must be declared an interface");
		                } else {
		                	//获取service的class
		                	Class serviceC = Class.forName(field.getType().getName());
		    				//获取service实现类的class
//		    				Class serviceImplC = Class.forName(serviceC.getPackage().getName()+".impl."+serviceC.getSimpleName()+"Impl");
		    				//设置实现类对象给 注解接口
//		    				field.set(c, serviceImplC.newInstance());
		                	for(String key : serviceImplCMap.keySet()) {
		                		if(key.equals(serviceC.getName())) {
		                			field.setAccessible(true); //暴力破解
		                			field.set(obj, ((Class)serviceImplCMap.get(key)).newInstance());
		                		}
		                	}
		                }
		            }
			}
		}
	}
}
